#ifndef __H_MATCH__
#define __H_MATCH__
#include "util.hpp"
#include <list>
#include "room.hpp"
#include "db.hpp"
#include "online.hpp"
#include <mutex>
#include <thread>
#include <condition_variable>
template<class T>
class match_queue
{
    private:
        std::list<T> _queue;
        std::mutex _mutex;
        std::condition_variable _cond;
    public:
        match_queue(){DLOG("匹配队列创建成功！！");}
        ~match_queue(){DLOG("匹配队列已被释放！！");}
        bool push(const T& val){
            std::unique_lock<std::mutex> lock(_mutex);
            _queue.push_back(val);
            _cond.notify_all();
            return true;
        }
        bool pop(T& val){
            std::unique_lock<std::mutex> lock(_mutex);
            if(_queue.size() <= 0) return false;
            val = _queue.front();
            _queue.pop_front();
            return true;
        }
        bool erase(const T& val)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            for(auto iter = _queue.begin() ; iter != _queue.end() ; ++iter)
            {
                if(*iter == val)
                {
                    _queue.erase(iter);
                    return true;
                }
            }
            return false;
        }
        void wait()
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _cond.wait(lock);
        }
        int size()
        {
            std::unique_lock<std::mutex> lock(_mutex);
            return _queue.size();
        }
        bool empty()
        {
            std::unique_lock<std::mutex> lock(_mutex);
            return _queue.size() == 0;
        }
};

class matcher
{
    private:
        std::thread _th_bronze;
        std::thread _th_silver;
        std::thread _th_golden;
        //青铜选手匹配队列
        match_queue<uint64_t> _q_bronze;
        //白银选手匹配队列
        match_queue<uint64_t> _q_silver;
        //黄金选手匹配队列
        match_queue<uint64_t> _q_golden;
        room_manager* _rm;
        online_user_manage* _om;
        user_table* _ut;
    private:
        //线程函数入口
        void handler_match(match_queue<uint64_t>& m_queue)
        {
            while(true)
            {
                //判断队列人数是否大于2，<2则阻塞等待
                while(m_queue.size() < 2)
                {
                    m_queue.wait();
                }
                //走下来代表人数够了，出队两个玩家
                uint64_t uid1,uid2;
                bool ret = m_queue.pop(uid1);
                if(ret == false) continue;
                ret = m_queue.pop(uid2);
                if(ret == false)
                {
                    add(uid1);
                    continue;
                }
                //校验两个玩家是否在线，如果有人掉线，则要把另一个人重新添加入队列
                wsserver_t::connection_ptr conn1 = _om->get_conn_from_hall(uid1);
                if(conn1.get() == nullptr)
                {
                    add(uid2);
                    continue;
                }
                wsserver_t::connection_ptr conn2 = _om->get_conn_from_hall(uid2);
                if(conn2.get() == nullptr)
                {
                    add(uid1);
                    continue;
                }
                //为两个玩家创建房间，并将玩家加入房间中
                room_ptr rp = _rm->create_room(uid1,uid2);
                DLOG("创建房间成功，uid1:%d,uid2:%d",uid1,uid2);
                if(rp.get() == nullptr)
                {
                    add(uid1),add(uid2);
                    continue;
                }
                //对两个玩家进行响应
                Json::Value json_resp;
                json_resp["optype"] = "match_success";
                json_resp["result"] = true;
                std::string body;
                json_util::Serialize(json_resp,body);
                conn1->send(body);
                conn2->send(body);
            }
        }
        void th_bronze_entry(){handler_match(_q_bronze);}
        void th_silver_entry(){handler_match(_q_silver);}
        void th_golden_entry(){handler_match(_q_golden);}
    public:
        matcher(room_manager* rm , online_user_manage* om , user_table* ut)
        :_rm(rm) , _om(om) , _ut(ut),
        _th_bronze(std::thread(&matcher::th_bronze_entry,this)),
        _th_silver(std::thread(&matcher::th_silver_entry,this)),
        _th_golden(std::thread(&matcher::th_golden_entry,this))
        {
            DLOG("匹配队列管理对象已被创建！！");
        }
        ~matcher()
        {
            DLOG("匹配队列管理对象已被销毁！！");
        }
        bool add(uint64_t uid)
        {
            //根据玩家的天梯分数，来判定玩家档次，添加到不同的匹配队列中
            Json::Value user;
            if(_ut->select_by_id(uid,user) == false)
            {
                ELOG("未找到uid:%d 该用户信息！！",uid);
                return false;
            }
            int score = user["score"].asInt();
            if(score < 2000)
            {
                //添加到青铜匹配队列
                _q_bronze.push(uid);
            }
            else if(score >= 2000 && score < 2500)
            {
                //添加到白银匹配队列
                _q_silver.push(uid);
            }
            else if(score >= 2500)
            {
                //添加到黄金匹配队列
                _q_golden.push(uid);
            }
            return true;
            
        }
        
        bool del(uint64_t uid)
        {
            Json::Value user;
            if(_ut->select_by_id(uid,user) == false)
            {
                ELOG("未找到uid:%d 该用户信息！！",uid);
                return false;
            }

            int score = user["score"].asInt();
            if(score < 2000)
            {
                _q_bronze.erase(uid);
            }
            else if(score >= 2000 && score < 2500)
            {
                _q_silver.erase(uid);
            }
            else if(score >= 2500)
            {
                _q_golden.erase(uid);
            }
            return true;
            
        }
};


#endif